package com.zjny.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.zjny.constant.CommonConstant;

import java.text.DecimalFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * packageName com.zjny.util
 *
 * @author cui haida
 * @version JDK 8
 * 2025/06/18
 */
public class ConvertUtils extends Convert {
    /**
     * 一十开头的变成十开头的
     * 一十一 -> 十一
     *
     * @param value 汉字表达法
     * @return 一十开头的变成十开头的
     */
    public static String handleChineseNum(String value) {
        if (value.startsWith("一十")) {
            value = value.substring(1);
        }
        return value;
    }

    /**
     * 数字格式化
     * 0 ~ 10 -> 零、一、二、三、四、五、六、七、八、九、十
     *
     * @param index 数字字符(0 ~ 9)
     * @return 转成对应中文的结果
     */
    public static char formatDigit(int index) {
        if (index <= 0 || index > 10) {
            return '〇';
        }
        return CommonConstant.CHAR_SIMPLE_DIGITS[index];
    }

    /**
     * 对应的数字变成千分位分割符
     * 1234.56 -> 1,234.56
     *
     * @param number 对应的数字
     * @return 填成对应的千分位分隔符
     */
    public static String addThousandCentimetres(String number) {
        if (!number.contains(CommonConstant.SPLIT_POINT) && number.length() == 4) {
            return number;
        } else {
            DecimalFormat df = new DecimalFormat(CommonConstant.DECIMAL_FORMAT);
            return df.format(Double.parseDouble(number));
        }
    }

    /**
     * 所有的繁体数字 -> 简写的数字：壹 -> 一
     *
     * @param number 数字
     * @return 结果
     */
    public static String transAllBigToSmall(String number) {
        String ans = number;
        for (int i = 0; i < CommonConstant.BIG_CHINESE_NUMBERS.length; i++) {
            ans = ans.replace(CommonConstant.BIG_CHINESE_NUMBERS[i], CommonConstant.SMALL_CHINESE_NUMBERS[i]);
        }
        // 两 -> 二
        ans = ans.replace("两", CommonConstant.SMALL_CHINESE_NUMBERS[1]);
        return ans;
    }


    /**
     * 汉字数字转成阿拉伯数字
     *
     * @param chineseNumber 汉字数字
     * @return 转成阿拉伯数字的结果
     */
    public static String convertChineseToNum(String chineseNumber) {

        String DIGIT_REGEX = "\\d+(\\.\\d+)?";

        if (ReUtil.isMatch(DIGIT_REGEX, chineseNumber)) {
            return chineseNumber;
        }
        chineseNumber = transAllBigToSmall(chineseNumber);
        StringBuilder decimal = new StringBuilder();
        String rate = CommonConstant.EMPTY;
        // 如果有“点”
        if (chineseNumber.contains(CommonConstant.SPLIT_CHN_POINT)) {
            String intNum = StrUtil.subBefore(chineseNumber, CommonConstant.SPLIT_CHN_POINT, false);
            String decimalNum = StrUtil.subAfter(chineseNumber, CommonConstant.SPLIT_CHN_POINT, false);
            // 2:中文标准化
            intNum = standardChnNumber(intNum);
            // 3:转化追加
            for (int i = 0; i < decimalNum.length(); i++) {
                int num = ArrayUtil.indexOf(CommonConstant.SIMPLE_DIGITS, String.valueOf(decimalNum.charAt(i)));
                if (num > 0) {
                    decimal.append(num);
                }
                rate = Convert.chineseToNumber(intNum) + CommonConstant.SPLIT_POINT + decimal;
            }
        } else {
            String intNum = standardChnNumber(chineseNumber);
            rate = String.valueOf(Convert.chineseToNumber(intNum));
        }
        return rate;
    }

    /**
     * 把中文数字标准化
     *
     * @param value 中文数字的值
     * @return 如果是十开头，改成一十
     */
    public static String standardChnNumber(String value) {
        int index = value.indexOf(CommonConstant.TEN);
        if (index == 0) {
            value = CommonConstant.SIMPLE_DIGITS[1] + value;
        } else if (index == 1 && CommonConstant.CHAR_SIMPLE_DIGITS[1] == (value.charAt(0))) {
            value = StrUtil.subAfter(value, CommonConstant.CHAR_SIMPLE_DIGITS[1], false);
        }
        return value;
    }


    /**
     * 整型数组转成List
     *
     * @param array 数组
     * @return 结果
     */
    public static List<Integer> intArrayToList(int[] array) {
        List<Integer> ans = new ArrayList<>();
        return Arrays.stream(array).boxed().collect(Collectors.toList());
    }

    /**
     * 浮点型数组转成List
     *
     * @param array 数组
     * @return 结果
     */
    public static List<Double> doubleArrayToList(double[] array) {
        List<Double> ans = new ArrayList<>();
        return Arrays.stream(array).boxed().collect(Collectors.toList());
    }

    /**
     * 长整型数组转成List
     *
     * @param array 数组
     * @return 结果
     */
    public static List<Long> longArrayToList(long[] array) {
        List<Long> ans = new ArrayList<>();
        return Arrays.stream(array).boxed().collect(Collectors.toList());
    }

    /**
     * 将collection转化为类型不变的map<br>
     *
     * @param collection 需要转化的集合
     * @param key        V类型转化为K类型的lambda方法
     * @param <V>        collection中的泛型
     * @param <K>        map中的key类型
     * @return 转化后的map
     */
    public static <V, K> Map<K, V> toIdentityMap(Collection<V> collection, Function<V, K> key) {
        if (CollUtil.isEmpty(collection)) {
            return MapUtil.newHashMap();
        }
        return collection.stream().filter(Objects::nonNull).collect(Collectors.toMap(key, Function.identity(), (l, r) -> l));
    }

    /**
     * 将Collection转化为map(value类型与collection的泛型不同)<br>
     * CollUtils.toMap(list, e -> e.getId(), e -> e)
     *
     * @param collection 需要转化的集合
     * @param key        E类型转化为K类型的lambda方法
     * @param value      E类型转化为V类型的lambda方法
     * @param <E>        collection中的泛型
     * @param <K>        map中的key类型
     * @param <V>        map中的value类型
     * @return 转化后的map
     */
    public static <E, K, V> Map<K, V> toMap(Collection<E> collection, Function<E, K> key, Function<E, V> value) {
        if (CollUtil.isEmpty(collection)) {
            return MapUtil.newHashMap();
        }
        return collection.stream().filter(Objects::nonNull).collect(Collectors.toMap(key, value, (l, r) -> l));
    }

    /**
     * 将collection按照规则(比如有相同的班级id)分类成map<br>
     * CollUtils.groupByKey(list, e -> e.getClassId())
     *
     * @param collection 需要分类的集合
     * @param key        分类的规则
     * @param <E>        collection中的泛型
     * @param <K>        map中的key类型
     * @return 分类后的map
     */
    public static <E, K> Map<K, List<E>> groupByKey(Collection<E> collection, Function<E, K> key) {
        if (CollUtil.isEmpty(collection)) {
            return MapUtil.newHashMap();
        }
        return collection
                .stream().filter(Objects::nonNull)
                // 通过指定的key分组
                .collect(Collectors.groupingBy(key, LinkedHashMap::new, Collectors.toList()));
    }

    /**
     * 将collection转化为List集合，但是两者的泛型不同<br>
     * CollUtils.toList(list, e -> e.getId())
     *
     * @param collection 需要转化的集合
     * @param function   collection中的泛型转化为list泛型的lambda表达式
     * @param <E>        collection中的泛型
     * @param <T>        List中的泛型
     * @return 转化后的list
     */
    public static <E, T> List<T> toList(Collection<E> collection, Function<E, T> function) {
        if (CollUtil.isEmpty(collection)) {
            return CollUtil.newArrayList();
        }
        return collection.stream().map(function).filter(Objects::nonNull).collect(Collectors.toList());
    }

    /**
     * 将collection转化为Set集合，但是两者的泛型不同<br>
     * CollUtils.toSet(list, e -> e.getId())
     *
     * @param collection 需要转化的集合
     * @param function   collection中的泛型转化为set泛型的lambda表达式
     * @param <E>        collection中的泛型
     * @param <T>        Set中的泛型
     * @return 转化后的Set
     */
    public static <E, T> Set<T> toSet(Collection<E> collection, Function<E, T> function) {
        if (CollUtil.isEmpty(collection) || function == null) {
            return CollUtil.newHashSet();
        }
        return collection
                .stream()
                .map(function)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
    }

    /**
     * 月和日的转换
     *
     * @param dateStr 日期字符串
     * @return 转换后的结果
     */
    public static String doTransForMonthAndDay(String dateStr) {
        StringBuilder sbd = new StringBuilder();
        int monthInt = Integer.parseInt(dateStr);
        // 1号到9号
        if (monthInt < 10) {
            sbd.append(ConvertUtils.formatDigit(monthInt));
        } else {
            // 10号-31号
            int consult = monthInt / 10;
            int remainder = monthInt % 10;
            if (consult > 1) {
                sbd.append(ConvertUtils.formatDigit(consult));
            }
            sbd.append(CommonConstant.SIMPLE_DIGITS[11]);
            if (remainder != 0) {
                sbd.append(ConvertUtils.formatDigit(remainder));
            }
        }
        return sbd.toString();
    }
}